package com.amor.widget

import android.annotation.SuppressLint
import android.content.Context
import android.graphics.Bitmap
import android.net.Uri
import android.net.http.SslError
import android.os.SystemClock
import android.text.TextUtils
import android.util.AttributeSet
import android.view.ViewGroup
import android.webkit.*
import com.hy.frame.util.LogUtil

class ExWebView : WebView {
    var lastPageStartTime = 0L
    var mCurUrl:String? = null

    constructor(context: Context) : super(context)
    constructor(context: Context, attrs: AttributeSet?) : super(context, attrs)
    constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr)
    constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int, defStyleRes: Int) : super(context, attrs, defStyleAttr, defStyleRes)
    constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int, privateBrowsing: Boolean) : super(context, attrs, defStyleAttr, privateBrowsing)


    @SuppressLint("SetJavaScriptEnabled")
    fun initWebSettings(mode: Int) {
        settings.apply {
            // 设置WebView支持JavaScript
            javaScriptEnabled = true
            defaultTextEncodingName = "utf-8" //默认UTF-8
            setSupportZoom(false) //设置WebView是否支持使用屏幕控件或手势进行缩放，默认是true，支持缩放
            displayZoomControls = false //设置WebView使用内置缩放机制时，是否展现在屏幕缩放控件上，默认true，展现在控件上。
            loadWithOverviewMode = true//是否允许WebView度超出以概览的方式载入页面，默认false。即缩小内容以适应屏幕宽度。该项设置在内容宽度超出WebView控件的宽度时生效，例如当getUseWideViewPort() 返回true时。
            //mediaPlaybackRequiresUserGesture = true //设置WebView是否通过手势触发播放媒体，默认是true，需要手势触发
            //builtInZoomControls = false //设置WebView是否使用其内置的变焦机制，该机制集合屏幕缩放控件使用，默认是false，不使用内置变焦机制
            allowFileAccess = true //设置在WebView内部是否允许访问文件，默认允许访问。
            allowContentAccess = true //是否允许在WebView中访问内容URL（Content Url），默认允许。内容Url访问允许WebView从安装在系统中的内容提供者载入内容。
            saveFormData = false
            domStorageEnabled = true
            //webview 从Lollipop(5.0)开始 webview默认不允许混合模式，https当中不能加载http资源，如果要加载，需单独设置开启。
            mixedContentMode = WebSettings.MIXED_CONTENT_ALWAYS_ALLOW
            blockNetworkImage = false
            allowUniversalAccessFromFileURLs = true
            cacheMode = mode
        }
    }

    /**
     * 把View从父布局剥离，client事件解耦
     */
    fun strip() {
        if (parent is ViewGroup) {
            (parent as ViewGroup).removeView(this)
        }
        webViewClient = webExViewClient
        webChromeClient = webExChromeClient

    }

    /**
     * 跳转到空白页并清空浏览记录
     */
    fun clear() {
        loadData("<html><head></head><body></body></html>", "text/html", "utf-8")
        clearHistory()
        LogUtil.d(javaClass, "clear canGoBack=" + canGoBack())
    }

    /**
     * 预加载对列
     */
    private val caches = HashMap<String, Boolean>()
    private var mPreCallback: PreCallback? = null

    /**
     * 预加载
     */
    fun preLoad(url: String, callback: PreCallback) {
        this.mPreCallback = callback
        caches[url] = false
        lastPageStartTime = 0
        loadUrl(url)
    }

    override fun loadUrl(url: String) {
        this.mCurUrl = url
        super.loadUrl(url)
    }

    /**
     * 是否已经预加载
     * @param url 地址
     * @param top 是否在顶部
     */
    fun isPrePageFinished(url: String, top: Boolean = false): Boolean {
        if (caches.containsKey(url) && caches[url]!!){
            if (top)
                return TextUtils.equals(url, mCurUrl)
            return true
        }
        return false
    }

    private val webExViewClient = object : WebViewClient() {
        private var loadError = false
        override fun onReceivedSslError(view: WebView?, handler: SslErrorHandler?, error: SslError?) {
            LogUtil.d(TAG, "onReceivedSslError error=$error")
            handler?.proceed()
        }

        override fun shouldOverrideUrlLoading(view: WebView?, url: String?): Boolean {
            LogUtil.d(TAG, "shouldOverrideUrlLoading url=$url")
            //阻止协议跳转
            if (url.isNullOrEmpty()) return true
            if (url.startsWith("http://") || url.startsWith("https://"))
                view?.loadUrl(url)
            return true
        }

        override fun shouldOverrideUrlLoading(view: WebView?, request: WebResourceRequest?): Boolean {
            return super.shouldOverrideUrlLoading(view, request)
        }

        override fun onLoadResource(view: WebView?, url: String?) {
            LogUtil.d(TAG, "onLoadResource url=$url")
        }

        override fun onPageStarted(view: WebView?, url: String?, favicon: Bitmap?) {
            LogUtil.d(TAG, "onPageStarted url=$url")
            lastPageStartTime = SystemClock.elapsedRealtime();
            loadError = false
            if (!url.isNullOrBlank() && caches.containsKey(url))
                mPreCallback?.onPrePageStarted(url)
        }

        override fun onPageFinished(view: WebView?, url: String?) {
            LogUtil.d(TAG, "onPageFinished url=$url")
            LogUtil.d(TAG, "onPageFinished time=%sms".format(SystemClock.elapsedRealtime() - lastPageStartTime))
            showConsole("页面加载耗时=%sms\n".format(SystemClock.elapsedRealtime() - lastPageStartTime))
            if (!url.isNullOrBlank() && caches.containsKey(url)) {
                caches[url] = true
                mPreCallback?.onPrePageFinished(url)
            }

//                if (loadError) {
//                    view?.post {
//                        //loading?.showError("网络异常，请稍候重试")
//                    }
//                    return
//                }
//                if (loadAgain) return
//                view?.post {
//                    loadAgain = true
//                    loading?.hide()
//                }
        }

        override fun onReceivedError(view: WebView?, request: WebResourceRequest?, error: WebResourceError?) {
            if (request == null) return
            val url = request.url?.toString()
            LogUtil.d(TAG, "onReceivedError url=$url")
            if (request.isForMainFrame) {
                loadError = true
            }
            if (!url.isNullOrBlank() && caches.containsKey(url))
                mPreCallback?.onPrePageError(url)
        }

    }
    private val webExChromeClient = object : WebChromeClient() {
        override fun onJsAlert(view: WebView?, url: String?, message: String?, result: JsResult?): Boolean {
//            view?.post {
//                showToast(message)
//            }
            result?.confirm()
            return true
        }

        override fun onCloseWindow(window: WebView?) {

        }

        override fun onConsoleMessage(consoleMessage: ConsoleMessage?): Boolean {
            LogUtil.d(TAG, "msg==%s,line=%s,id=%s".format(consoleMessage?.message(), consoleMessage?.lineNumber(), consoleMessage?.sourceId()))
            return true
        }

        //For Android API >= 21 (5.0 OS)
        override fun onShowFileChooser(webView: WebView?, filePathCallback: ValueCallback<Array<Uri>>?, fileChooserParams: FileChooserParams?): Boolean {
            if (filePathCallback != null)
                webView?.post {
                    //showFileChooser(filePathCallback)
                }
            return true
        }

        override fun onReceivedTitle(view: WebView?, title: String?) {
//            if (!mTitle.isNullOrEmpty()) return
//            view?.post {
//                if (!title.isNullOrEmpty() && !title.contains("//"))
//                    toolbar?.setTitle(title)
//            }
        }
    }

    private fun showConsole(msg: String?) {
        LogUtil.d(TAG, msg)
    }

    interface PreCallback {
        fun onPrePageStarted(url: String)
        fun onPrePageFinished(url: String)
        fun onPrePageError(url: String)
    }

    companion object {
        private const val TAG = "ExWebView"
    }
}